var exports = {
	group: null,
};

var Matrix = require("./Matrix.js");
var Control = require("./Control.js");
var DOMControl = require("./DOMControl.js");
var ControlSet = require("./ControlSet.js");
var DOMTransformTool = require("./DOMTransformTool.js");

var toolElem = null;
var tool = null;
var thedom = document.body;
var group = null;

var Mouse = {};
Mouse.x = 0;
Mouse.y = 0;

Mouse.START = "mousedown";
Mouse.MOVE = "mousemove";
Mouse.END = "mouseup";

var currElement = null;

var prex = 0;
var prey = 0;

exports.prexy = function(x, y) {
	prex = x;
	prey = y;
}

Mouse.get = function(event, elem) {
	if (!elem) {
		elem = event.currentTarget;
	}

	if (event.touches) {
		if (event.touches.length) {
			Mouse.x = parseInt(event.touches[0].pageX);
			Mouse.y = parseInt(event.touches[0].pageY);
		}
	} else {
		// mouse events
		Mouse.x = parseInt(event.clientX);
		Mouse.y = parseInt(event.clientY);
	}

	var rect = elem.getBoundingClientRect();
	Mouse.x += elem.scrollLeft - elem.clientLeft - rect.left - prex;
	Mouse.y += elem.scrollTop - elem.clientTop - rect.top - prey;
	return Mouse;
}

exports.init = function() {
	exports.group = group = Design.paper.g();
	group.attr("displayType", "tool");
	toolElem = document.getElementById("svgView");
	tool = new DOMTransformTool(group.node);
	ControlSet.controlClass = DOMControl;
	var controls = getCustomControls();
	tool.setControls(controls);
	toolElem.addEventListener(Mouse.START, exports.down);

	var canSelectType = ["Control", "Element"];

	document.addEventListener("mousedown", function(e) {
		var target = e.target;
		var type = target.getAttribute("displayType");
		var svgview = $("#svgView")[0];
		var isInSvg = $(target).parents("#svgView");
		if (type && canSelectType.indexOf(type) != -1) {

		} else if (isInSvg.length > 0 || target == svgview) {
			//exports.setTarget(null);
		}
	});

	return group;
}

exports.getTarget = function() {
	return currElement;
}

exports.setTarget = function($ele) {
	if (currElement) {
		currElement.unselect();
	}
	if ($ele) {
		var element = $ele.element;
		var bbox = element.getBBox(true);
		var em = element.matrix;
		var m = new Matrix(em.a, em.b, em.c, em.d, em.e, em.f);
		if ($ele.type == "text") {
			var dmatrix = $ele.dmatrix.clone();
			dmatrix.concat(m);
			m = dmatrix;
		}
		$ele._transform = new Transformable(bbox.width, bbox.height, m, $ele);
		$ele._transform.element = element;
		tool.setTarget($ele._transform);
	} else {
		tool.setTarget(null);
	}

	currElement = $ele;
	window.currElement = currElement;

	tool.draw();
}

exports.update = function() {
	var target = tool.target;
	var element = target.element;
	var bbox = element.getBBox(true);
	target.width = bbox.w;
	target.height = bbox.h;
	tool.updateFromTarget();
	exports.draw();
}

exports.updateFromTarget = function(){
	tool.updateFromTarget();
}

exports.down = function(event) {
	Mouse.get(event, toolElem);
	var controlled = tool.start(Mouse.x, Mouse.y);

	// if tool wasnt selected and being controlled
	// attempt to make a new selection at this location
	if (!controlled && tool.target) {
		// selection occurred
		// force select the translate control
		// to be able to start moving right away
		controlled = tool.start(Mouse.x, Mouse.y, exports.findControlByType(Control.TRANSLATE));
	}

	if (controlled) {
		// events for moving selection
		thedom.addEventListener(Mouse.MOVE, exports.move);
		document.addEventListener(Mouse.END, exports.up);
	}

	exports.draw();
	event.preventDefault();
};

exports.findControlByType = function(type) {
	var i = 0;
	var n = tool.controls.length;
	for (i = 0; i < n; i++) {
		if (tool.controls[i].type == type) {
			return tool.controls[i];
		}
	}
	return null;
}

exports.move = function(event) {
	if (currElement) {
		Mouse.get(event, toolElem);
		tool.move(Mouse.x, Mouse.y);
	}
	exports.draw();
	event.preventDefault();
};

exports.up = function(event) {
	if (currElement) {
		tool.end();
	}
	thedom.removeEventListener(Mouse.MOVE, exports.move);
	document.removeEventListener(Mouse.END, exports.up);
	exports.draw();

	//判断是否完全脱离裁剪范围，用于判断是否删除
	var elebox = tool.target.element.getBBox();
	var probox = Design.mainEditer.getEditeRect();
	if (elebox.x > probox.x2 || elebox.x2 < probox.x || elebox.y2 < probox.y || elebox.y > probox.y2) {
		var face = currElement.face;
		face.removeElement(tool.target.owner.id);
		exports.setTarget(null);
	}

	event.preventDefault();
};

exports.draw = function() {
	if (tool.target) {
		var tm = tool.target.matrix;
		var newMatrix = new Snap.Matrix(tm.a, tm.b, tm.c, tm.d, tm.x, tm.y);
		if (currElement.dmatrix) {
			var dinv = currElement.dmatrix.clone();
			dinv.invert();
			newMatrix.add(dinv.a, dinv.b, dinv.c, dinv.d, dinv.x, dinv.y);
		}
		tool.target.element.transform(newMatrix);
		tool.target.owner.update();

		//判断是否超出裁剪范围
		var elebox = tool.target.element.getBBox();
		var probox = Design.mainEditer.getEditeRect();
		if (elebox.x < probox.x || elebox.x2 > probox.x2 || elebox.y < probox.y || elebox.y2 > probox.y2) {
			tool.strokeStyle = "#ff0000";
		} else {
			tool.strokeStyle = "#08F";
		}
		
		if (elebox.x > probox.x2 || elebox.x2 < probox.x || elebox.y2 < probox.y || elebox.y > probox.y2) {
			tool.strokeStyle = "#00ffff";
		}
	}
	tool.draw();
}

function getCustomControls() {
	var translater = new DOMControl(Control.TRANSLATE);
	// on the target's shape, not the control point
	translater.hitTestTarget = true;

	var targetContent = new DOMControl(Control.TARGET);
	return [
		targetContent, // renders target between controls
		translater,
		new DOMControl(Control.BORDER),
		new DOMControl(Control.SCALE_X, 0, .5, 0, 0, 10),
		new DOMControl(Control.SCALE_X, 1, .5, 0, 0, 10),
		new DOMControl(Control.SCALE_Y, .5, 0, 0, 0, 10),
		new DOMControl(Control.SCALE_Y, .5, 1, 0, 0, 10),
		new DOMControl(Control.SCALE_UNIFORM, 0, 0, 0, 0, 10),
		new DOMControl(Control.SCALE_UNIFORM, 0, 1, 0, 0, 10),
		new DOMControl(Control.SCALE_UNIFORM, 1, 0, 0, 0, 10),
		new DOMControl(Control.SCALE_UNIFORM, 1, 1, 0, 0, 10),
		new DOMControl(Control.ROTATE_SCALE, 1, 0, 15, -15, 10),
		new DOMControl(Control.ROTATE, .5, 0, 0, -20)
	];
}

/**
 * Interface for Transform targets.
 */
function Transformable(width, height, matrix, owner) {
	this.width = width || 0; // Number
	this.height = height || 0; // Number
	this.matrix = matrix || new Matrix(1, 0, 0, 1, 0, 0); // Matrix
	this.owner = owner; // *
	this.changed = null; // Function
}

module.exports = exports;
